package com.levi.juc.volatiletest;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 保证可见性
 * 1.不加volatile的情况下，主线程把num的值更改之后，上面的线程并不会得到最新的值，所以还是一直处于死循环中，没有保证可见性
 * 2.加上volatile之后 就可以保证可见性 ,主线程把num的值修改之后，thread线程就立刻获取主存中最新的值
 *
 *  指令重排:JVM能够根据处理器的特性（CPU的多级缓存系统、多核处理器等）适当的重新排序机器指令，使机器指令更符合CPU的执行特点，最大限度的发挥机器的性能，提高效率
 *
 * volatile相当于在变量前后各加了一层屏障，这个屏障有两个作用
 * 1.保证可见性，
 * 2.禁止指令重排:  编译器在生成字节码时， 会在指令序列中插入内存屏障。会多出一个 lock 前缀指令
 * 先于这个内存屏障的指令必须先执行，后于这个内存屏障 的指令必须后执行
 */
public class VolatileTest01 {
    private volatile static int num = 0;
    public static void main(String[] args) throws InterruptedException {
   /*     ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
                1,
                2,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy());
        threadPoolExecutor.execute(()->{
            while (num == 0) {

            }
        });*/
        new Thread(()->{
            while (num == 0) {

            }
        }).start();
        TimeUnit.SECONDS.sleep(1);
        //不加volatile的情况下，主线程把num的值更改之后，上面的线程并没有得到最新的值，所以还是一直处于死循环中，没有保证可见性
        num = 1;
        System.out.println(num);
    }
}
